﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;

namespace System.Linq.Functional
{
    public static class Async
    {
        public static Action AsAsync(this Action action)
        {
            return () =>
            {
                ThreadPool.QueueUserWorkItem(_ => action());
            };
        }

        public static Action<TArg1> AsAsync<TArg1>(this Action<TArg1> action)
        {
            return (arg1) =>
            {
                ThreadPool.QueueUserWorkItem(_ => action(arg1));
            };
        }

        public static Action<TArg1, TArg2> AsAsync<TArg1, TArg2>(this Action<TArg1, TArg2> action)
        {
            return (arg1, arg2) =>
            {
                ThreadPool.QueueUserWorkItem(_ => action(arg1, arg2));
            };
        }

        public static Action<TArg1, TArg2, TArg3> AsAsync<TArg1, TArg2, TArg3>(this Action<TArg1, TArg2, TArg3> action)
        {
            return (arg1, arg2, arg3) =>
            {
                ThreadPool.QueueUserWorkItem(_ => action(arg1, arg2, arg3));
            };
        }

        public static Action<TArg1, TArg2, TArg3, TArg4> AsAsync<TArg1, TArg2, TArg3, TArg4>(this Action<TArg1, TArg2, TArg3, TArg4> action)
        {
            return (arg1, arg2, arg3, arg4) =>
            {
                ThreadPool.QueueUserWorkItem(_ => action(arg1, arg2, arg3, arg4));
            };
        }

        #region Execute
        public static void ExecuteAsync(this Action action)
        {
            action.AsAsync()();
        }

        public static void ExecuteAsync<TArg1>(this Action<TArg1> action, TArg1 arg1)
        {
            action.AsAsync()(arg1);
        }

        public static void ExecuteAsync<TArg1, TArg2>(
            this Action<TArg1, TArg2> action, 
            TArg1 arg1, 
            TArg2 arg2)
        {
            action.AsAsync()(arg1, arg2);
        }

        public static void ExecuteAsync<TArg1, TArg2, TArg3>(
            this Action<TArg1, TArg2, TArg3> action,
            TArg1 arg1,
            TArg2 arg2, 
            TArg3 arg3)
        {
            action.AsAsync()(arg1, arg2, arg3);
        }

        public static void ExecuteAsync<TArg1, TArg2, TArg3, TArg4>(
            this Action<TArg1, TArg2, TArg3, TArg4> action, 
            TArg1 arg1, 
            TArg2 arg2,
            TArg3 arg3,
            TArg4 arg4)
        {
            action.AsAsync()(arg1, arg2, arg3, arg4);
        }
        #endregion Execute
    }
}
